"""
应用初始化管理器
负责统一管理应用启动时的各种初始化操作
"""

import asyncio
from pathlib import Path
from typing import Dict, Any, Tuple

from config.chromadb_config import chroma_db
from config.database import init_database, get_db_session
from config.logging_config import get_logger
from constant.settings import settings
from mcp_tools.mcpClient import mcp_client
from pojo.ai_web_detail_tools_model import AIWebDetailToolsModel
from pojo.ai_web_mcp_tools_model import AIWebMCPToolsModel
from tools.ToolFactory import ToolFactory

logger = get_logger(__name__)


class AppInitializer:
    """应用初始化管理器"""

    def __init__(self):
        self.initialization_results: Dict[str, bool] = {}

    async def initialize_all(self) -> Dict[str, bool]:
        """执行所有初始化操作"""
        logger.info("🚀 开始应用初始化")

        # 定义初始化步骤
        init_steps = [
            ("database", self.init_database),
            ("chromadb", self.init_chromadb),
            ("tools", self.init_tools),
            ("mcp_client", self.init_mcp_client),
            ("upload_directory", self.init_upload_directory),
            ("global_tools_dict", self.init_global_tools_dict),
        ]

        # 执行初始化步骤
        for step_name, init_func in init_steps:
            try:
                await init_func()
                self.initialization_results[step_name] = True
            except Exception as e:
                self.initialization_results[step_name] = False
                logger.error(f"❌ {step_name} 初始化失败: {e}")

        # 输出初始化结果摘要
        self._log_initialization_summary()
        return self.initialization_results

    async def init_database(self):
        """初始化数据库"""
        await init_database()
        logger.info("✅ 数据库初始化完成")

    async def init_chromadb(self):
        """初始化ChromaDB向量数据库"""
        if chroma_db is None:
            raise Exception("ChromaDB实例为None，请检查配置")

        collection_info = chroma_db.get_collection_info()
        doc_count = collection_info.get('count', 0)
        embedding_model = settings.CHROMA_EMBEDDING_MODEL

        logger.info(f"✅ ChromaDB初始化完成 - 文档数量: {doc_count}, 嵌入模型: {embedding_model}")

    async def init_tools(self):
        """初始化工具到数据库"""
        session = next(get_db_session())
        try:
            results = ToolFactory.initialize_all_tools(session)
            success_count = sum(1 for success in results.values() if success)
            total_count = len(results)
            logger.info(f"✅ 工具初始化完成 - 成功: {success_count}/{total_count}")
        finally:
            session.close()

    async def init_mcp_client(self):
        """初始化MCP客户端"""
        default_servers = settings.DEFAULT_MCP_SERVERS
        if not default_servers:
            logger.info("ℹ️  未配置MCP服务器，跳过初始化")
            return

        connected_count = 0
        total_synced_tools = 0

        for server_name, server_config in default_servers.items():
            try:
                success, synced_tools = await self._connect_mcp_server(server_name, server_config)
                if success:
                    connected_count += 1
                    total_synced_tools += synced_tools
            except Exception as e:
                logger.error(f"MCP服务器 {server_name} 连接失败: {e}")

        logger.info(
            f"✅ MCP客户端初始化完成 - 服务器: {connected_count}/{len(default_servers)}, 工具: {total_synced_tools}")

    async def init_upload_directory(self):
        """初始化上传目录"""
        upload_dir = Path("uploads")
        upload_dir.mkdir(exist_ok=True)
        logger.info("✅ 上传目录初始化完成")

    async def init_global_tools_dict(self):
        """初始化全局工具字典"""
        from constant.tool_dict_config import toolDictConfig
        await toolDictConfig.init_global_tools_dict()
        logger.info("✅ 全局工具字典初始化完成")

    async def cleanup(self):
        """清理资源"""
        logger.info("🛑 开始资源清理")

        cleanup_timeout = 30
        try:
            await asyncio.wait_for(
                self._cleanup_mcp_client(),
                timeout=cleanup_timeout
            )
            logger.info("✅ 资源清理完成")
        except asyncio.TimeoutError:
            logger.warning(f"⚠️  资源清理超时({cleanup_timeout}秒)")
        except Exception as e:
            logger.error(f"❌ 资源清理异常: {e}", exc_info=True)

    async def _connect_mcp_server(self, server_name: str, server_config: dict) -> Tuple[bool, int]:
        """连接单个MCP服务器并同步工具"""
        try:
            # 连接MCP服务器
            success = await mcp_client.connect_from_json_schema(server_name, server_config)
            if not success:
                return False, 0

            # 同步工具到数据库
            session = next(get_db_session())
            try:
                # 获取或创建MCP工具记录
                mcp_tool = session.query(AIWebMCPToolsModel).filter(
                    AIWebMCPToolsModel.mcp_name == server_name
                ).first()

                if not mcp_tool:
                    mcp_tool = AIWebMCPToolsModel(
                        mcp_name=server_name,
                        description=f"MCP工具: {server_name}",
                        access_type=1,
                        status=1,
                        json_schema=server_config
                    )
                    session.add(mcp_tool)
                    session.commit()
                    session.refresh(mcp_tool)
                else:
                    mcp_tool.json_schema = server_config
                    mcp_tool.status = 1
                    session.commit()

                # 获取工具列表并同步
                tools = await mcp_client.get_tools(server_name)
                if not tools:
                    return True, 0

                existing_tools = session.query(AIWebDetailToolsModel).filter(
                    AIWebDetailToolsModel.parent_id == mcp_tool.id
                ).all()
                existing_tool_names = {tool.tool_name for tool in existing_tools}

                synced_count = 0
                for tool_info in tools:
                    try:
                        # 解析参数
                        parameters = self._parse_tool_parameters(tool_info.input_schema)

                        if tool_info.name in existing_tool_names:
                            # 更新现有工具
                            existing_tool = session.query(AIWebDetailToolsModel).filter(
                                AIWebDetailToolsModel.parent_id == mcp_tool.id,
                                AIWebDetailToolsModel.tool_name == tool_info.name
                            ).first()
                            if existing_tool:
                                existing_tool.description = tool_info.description or ""
                                existing_tool.set_parameters(parameters)
                                if not existing_tool.server_code:
                                    existing_tool.server_code = server_name
                        else:
                            # 创建新工具
                            new_tool = AIWebDetailToolsModel(
                                parent_id=mcp_tool.id,
                                tool_type=2,
                                tool_name=tool_info.name,
                                server_code=server_name,
                                description=tool_info.description or "",
                                is_enabled=True,
                                parameters=parameters
                            )
                            session.add(new_tool)

                        synced_count += 1

                    except Exception as tool_error:
                        logger.debug(f"同步工具 {tool_info.name} 失败: {tool_error}")
                        continue

                session.commit()
                return True, synced_count

            finally:
                session.close()

        except Exception as e:
            logger.debug(f"MCP服务器 {server_name} 连接异常: {e}")
            return False, 0

    def _parse_tool_parameters(self, input_schema):
        """解析工具参数"""
        parameters = []
        if input_schema and "properties" in input_schema:
            properties = input_schema["properties"]
            required_fields = input_schema.get("required", [])

            for param_name, param_def in properties.items():
                parameter = {
                    "param_name": param_name,
                    "param_type": param_def.get("type", "string"),
                    "description": param_def.get("description", ""),
                    "is_required": param_name in required_fields,
                    "default_value": param_def.get("default")
                }
                parameters.append(parameter)
        else:
            # 默认参数
            parameters = [{
                "param_name": "input",
                "param_type": "string",
                "description": "Tool input",
                "is_required": False,
                "default_value": None
            }]
        return parameters

    async def _cleanup_mcp_client(self):
        """清理MCP客户端"""
        await mcp_client.cleanup()

    def _log_initialization_summary(self):
        """输出初始化结果摘要"""
        successful = sum(1 for success in self.initialization_results.values() if success)
        total = len(self.initialization_results)

        if successful == total:
            logger.info(f"🎯 初始化完成 - 全部成功 ({successful}/{total})")
        else:
            failed_components = [name for name, success in self.initialization_results.items() if not success]
            logger.warning(f"🎯 初始化完成 - 部分失败 ({successful}/{total}) - 失败组件: {', '.join(failed_components)}")

    def get_initialization_status(self) -> Dict[str, Any]:
        """获取初始化状态"""
        successful = sum(1 for success in self.initialization_results.values() if success)
        total = len(self.initialization_results)

        return {
            "total_components": total,
            "successful_components": successful,
            "success_rate": f"{successful}/{total}",
            "all_successful": successful == total,
            "results": self.initialization_results.copy()
        }


# 创建全局初始化器实例
app_initializer = AppInitializer()
